package com.szeldon.declatest.eval;

import java.util.Date;
import java.util.Properties;

import org.testng.Assert;
import org.testng.annotations.Test;

import com.szeldon.declatest.eval.exceptions.EvaluationException;
import com.szeldon.declatest.eval.plugins.DefaultEvaluatorPlugin;
import com.szeldon.declatest.exec.TestSuiteExecHistory;
import com.szeldon.declatest.exec.events.dostep.jms.JmsMessageReceivedExecEvent;

/**
 * Unit tests for {@link ScenarioPartEvaluator} class.
 * 
 * @author szeldon
 * 
 */
public class ScenarioPartEvaluatorTest {
    @Test
    public void testExtractPluginNameAndExpression1() {
        String[] split = ScenarioPartEvaluator.extractPluginNameAndExpression("some#thing");
        Assert.assertEquals(split.length, 2);
        Assert.assertEquals(split[0], "some");
        Assert.assertEquals(split[1], "thing");
    }

    @Test
    public void testExtractPluginNameAndExpression2() {
        String[] split = ScenarioPartEvaluator.extractPluginNameAndExpression("thing");
        Assert.assertEquals(split.length, 2);
        Assert.assertEquals(split[0], "");
        Assert.assertEquals(split[1], "thing");
    }

    @Test
    public void testExtractPluginNameAndExpression3() {
        String[] split = ScenarioPartEvaluator.extractPluginNameAndExpression("");
        Assert.assertEquals(split.length, 2);
        Assert.assertEquals(split[0], "");
        Assert.assertEquals(split[1], "");
    }

    @Test
    public void testExtractPluginNameAndExpression4() {
        String[] split = ScenarioPartEvaluator.extractPluginNameAndExpression("some#other#thing");
        Assert.assertEquals(split.length, 2);
        Assert.assertEquals(split[0], "some");
        Assert.assertEquals(split[1], "other#thing");
    }

    @Test
    public void testProperEvaluateCondition1() throws EvaluationException {
        ScenarioPartEvaluator evaluator = new ScenarioPartEvaluator();
        evaluator.addPlugin(new DefaultEvaluatorPlugin());
        ConditionReturnValue returnValue = evaluator.evaluateCondition(null, null, "value", "equals", "value", null);
        Assert.assertEquals(returnValue.isEvaluatedTrue(), true);
        Assert.assertEquals(returnValue.getEvaluatedLeft(), "value");
        Assert.assertEquals(returnValue.getEvaluatedRight(), "value");
    }

    @Test
    public void testProperSimpleEvaluateCondition2() throws EvaluationException {
        ScenarioPartEvaluator evaluator = new ScenarioPartEvaluator();
        evaluator.addPlugin(new DefaultEvaluatorPlugin());
        ConditionReturnValue returnValue = evaluator.evaluateCondition(null, null, "value", "equals", "another value",
                null);
        Assert.assertEquals(returnValue.isEvaluatedTrue(), false);
        Assert.assertEquals(returnValue.getEvaluatedLeft(), "value");
        Assert.assertEquals(returnValue.getEvaluatedRight(), "another value");
    }

    @Test
    public void testProperSimpleEvaluateCondition3() throws EvaluationException {
        ScenarioPartEvaluator evaluator = new ScenarioPartEvaluator();
        evaluator.addPlugin(new DefaultEvaluatorPlugin());
        ConditionReturnValue returnValue = evaluator.evaluateCondition(null, null, "value", "equals", "another value",
                null);
        Assert.assertEquals(returnValue.isEvaluatedTrue(), false);
        Assert.assertEquals(returnValue.getEvaluatedLeft(), "value");
        Assert.assertEquals(returnValue.getEvaluatedRight(), "another value");
    }

    @Test
    public void testProperPropertyEvaluateCondition1() throws EvaluationException {
        ScenarioPartEvaluator evaluator = new ScenarioPartEvaluator();
        evaluator.addPlugin(new DefaultEvaluatorPlugin());
        Properties properties = new Properties();
        properties.put("some-key", "some value");
        ConditionReturnValue returnValue = evaluator.evaluateCondition(properties, null, "${some-key@property}",
                "equals", "some value", null);
        Assert.assertEquals(returnValue.isEvaluatedTrue(), true);
        Assert.assertEquals(returnValue.getEvaluatedLeft(), "some value");
        Assert.assertEquals(returnValue.getEvaluatedRight(), "some value");

    }

    @Test
    public void testProperPropertyEvaluateCondition2() throws EvaluationException {
        ScenarioPartEvaluator evaluator = new ScenarioPartEvaluator();
        evaluator.addPlugin(new DefaultEvaluatorPlugin());
        Properties properties = new Properties();
        properties.put("some-key", "some value");
        ConditionReturnValue returnValue = evaluator.evaluateCondition(properties, null, "${some-key@property}",
                "equals", "some bad value", null);
        Assert.assertEquals(returnValue.isEvaluatedTrue(), false);
        Assert.assertEquals(returnValue.getEvaluatedLeft(), "some value");
        Assert.assertEquals(returnValue.getEvaluatedRight(), "some bad value");
    }

    @Test
    public void testProperStepEvaluateCondition1() throws EvaluationException {
        ScenarioPartEvaluator evaluator = new ScenarioPartEvaluator();
        evaluator.addPlugin(new DefaultEvaluatorPlugin());
        TestSuiteExecHistory history = new TestSuiteExecHistory("testsuiteid");
        history.addExecEvent(new JmsMessageReceivedExecEvent("scenarioId", "event description", new Date(),
                "scenarioStepId", "stepDescription", "stepEndpointId", "stepRequestPath", "endpointDescription",
                "endpointUrl", "endpointSettingsId", "queue", "queueName", "some content"));
        ConditionReturnValue returnValue = evaluator.evaluateCondition(null, null, "${response@scenarioStepId@step}",
                "equals", "some content", history);
        Assert.assertEquals(returnValue.isEvaluatedTrue(), true);
        Assert.assertEquals(returnValue.getEvaluatedLeft(), "some content");
        Assert.assertEquals(returnValue.getEvaluatedRight(), "some content");
    }

    @Test
    public void testProperStepEvaluateCondition2() throws EvaluationException {
        ScenarioPartEvaluator evaluator = new ScenarioPartEvaluator();
        evaluator.addPlugin(new DefaultEvaluatorPlugin());
        TestSuiteExecHistory history = new TestSuiteExecHistory("testsuiteid");
        history.addExecEvent(new JmsMessageReceivedExecEvent("scenarioId", "event description", new Date(),
                "scenarioStepId", "stepDescription", "stepEndpointId", "stepRequestPath", "endpointDescription",
                "endpointUrl", "endpointSettingsId", "queue", "queueName", "some content"));
        ConditionReturnValue returnValue = evaluator.evaluateCondition(null, null, "${response@scenarioStepId@step}",
                "notEquals", "some content", history);
        Assert.assertEquals(returnValue.isEvaluatedTrue(), false);
        Assert.assertEquals(returnValue.getEvaluatedLeft(), "some content");
        Assert.assertEquals(returnValue.getEvaluatedRight(), "some content");
    }

    @Test
    public void testProperStepAndPropertyEvaluateCondition1() throws EvaluationException {
        ScenarioPartEvaluator evaluator = new ScenarioPartEvaluator();
        evaluator.addPlugin(new DefaultEvaluatorPlugin());
        TestSuiteExecHistory history = new TestSuiteExecHistory("testsuiteid");
        history.addExecEvent(new JmsMessageReceivedExecEvent("scenarioId", "event description", new Date(),
                "scenarioStepId", "stepDescription", "stepEndpointId", "stepRequestPath", "endpointDescription",
                "endpointUrl", "endpointSettingsId", "queue", "queueName", "some content"));
        Properties properties = new Properties();
        properties.put("some-key", "some value");

        ConditionReturnValue returnValue = evaluator.evaluateCondition(properties, null,
                "${response@scenarioStepId@step} ${some-key@property}", "equals", "some content some value", history);
        Assert.assertEquals(returnValue.isEvaluatedTrue(), true);
        Assert.assertEquals(returnValue.getEvaluatedLeft(), "some content some value");
        Assert.assertEquals(returnValue.getEvaluatedRight(), "some content some value");
    }

    @Test
    public void testProperStepAndPropertyEvaluateCondition2() throws EvaluationException {
        ScenarioPartEvaluator evaluator = new ScenarioPartEvaluator();
        evaluator.addPlugin(new DefaultEvaluatorPlugin());
        TestSuiteExecHistory history = new TestSuiteExecHistory("testsuiteid");
        history.addExecEvent(new JmsMessageReceivedExecEvent("scenarioId", "event description", new Date(),
                "scenario StepId", "stepDescription", "stepEndpointId", "stepRequestPath", "endpointDescription",
                "endpointUrl", "endpointSettingsId", "queue", "queueName", "some content"));
        Properties properties = new Properties();
        properties.put("some- key", "some value");

        ConditionReturnValue returnValue = evaluator.evaluateCondition(properties, null,
                "textBefore${response@scenario StepId@step} ${some- key@property}textafter", "equals",
                "textBeforesome content some valuetextafter", history);
        Assert.assertEquals(returnValue.isEvaluatedTrue(), true);
        Assert.assertEquals(returnValue.getEvaluatedLeft(), "textBeforesome content some valuetextafter");
        Assert.assertEquals(returnValue.getEvaluatedRight(), "textBeforesome content some valuetextafter");
    }

    @Test
    public void testProperStepAndPropertyAndNestedEvaluateCondition1() throws EvaluationException {
        ScenarioPartEvaluator evaluator = new ScenarioPartEvaluator();
        evaluator.addPlugin(new DefaultEvaluatorPlugin());
        TestSuiteExecHistory history = new TestSuiteExecHistory("testsuiteid");
        history.addExecEvent(new JmsMessageReceivedExecEvent("scenarioId", "event description", new Date(),
                "stepIdFromProperty", "stepDescription", "stepEndpointId", "stepRequestPath", "endpointDescription",
                "endpointUrl", "endpointSettingsId", "queue", "queueName", "some content"));
        Properties properties = new Properties();
        properties.put("some- key", "some value");
        properties.put("gimmeStepId", "stepIdFromProperty");

        ConditionReturnValue returnValue = evaluator.evaluateCondition(properties, null,
                "textBefore${response@${gimmeStepId@property}@step} ${some- key@property}textafter", "equals",
                "textBeforesome content some valuetextafter", history);
        Assert.assertEquals(returnValue.isEvaluatedTrue(), true);
        Assert.assertEquals(returnValue.getEvaluatedLeft(), "textBeforesome content some valuetextafter");
        Assert.assertEquals(returnValue.getEvaluatedRight(), "textBeforesome content some valuetextafter");
    }

    @Test(expectedExceptions = EvaluationException.class)
    public void testBadStepAndPropertyAndNestedEvaluateCondition1() throws EvaluationException {
        ScenarioPartEvaluator evaluator = new ScenarioPartEvaluator();
        evaluator.addPlugin(new DefaultEvaluatorPlugin());
        TestSuiteExecHistory history = new TestSuiteExecHistory("testsuiteid");
        history.addExecEvent(new JmsMessageReceivedExecEvent("scenarioId", "event description", new Date(),
                "scenarioStepId", "stepDescription", "stepEndpointId", "stepRequestPath", "endpointDescription",
                "endpointUrl", "endpointSettingsId", "queue", "queueName", "some content"));
        Properties properties = new Properties();
        properties.put("some- key", "some value");
        properties.put("gimmeStepId", "badStepIdFromProperty");

        ConditionReturnValue returnValue = evaluator.evaluateCondition(properties, null,
                "textBefore${response@${gimmeStepId@property}@step} ${some- key@property}textafter", "equals",
                "textBeforesome content some valuetextafter", history);

    }

    @Test
    public void testProperStepAndFunctionAndPropertyAndNestedEvaluateCondition1() throws EvaluationException {
        ScenarioPartEvaluator evaluator = new ScenarioPartEvaluator();
        evaluator.addPlugin(new DefaultEvaluatorPlugin());
        TestSuiteExecHistory history = new TestSuiteExecHistory("testsuiteid");
        history.addExecEvent(new JmsMessageReceivedExecEvent("scenarioId", "event description", new Date(),
                "stepIdFromProperty", "stepDescription", "stepEndpointId", "stepRequestPath", "endpointDescription",
                "endpointUrl", "endpointSettingsId", "queue", "queueName", "someContent"));
        Properties properties = new Properties();
        properties.put("some- key", "some value");
        properties.put("gimmeStepId", "stepIdFromProperty");

        ConditionReturnValue returnValue = evaluator.evaluateCondition(properties, null,
                "textBefore ${response@${gimmeStepId@property}@step} "
                        + "${datetime-14@function} ${some- key@property} textafter", "matches",
                "textBefore someContent \\d\\d\\d\\d\\d\\d\\d\\d\\d\\d\\d\\d\\d\\d some value textafter", history);
        Assert.assertEquals(returnValue.isEvaluatedTrue(), true);
        Assert.assertEquals(returnValue.getEvaluatedRight(),
                "textBefore someContent \\d\\d\\d\\d\\d\\d\\d\\d\\d\\d\\d\\d\\d\\d some value textafter");
    }
}
